<!-- 权限管理-角色管理 -->
<template>
    <!-- 子组件：顶部搜索 -->
    <Searchbox @searchEvent="searchRole" @resetEvent="resetRoleList" />
    <!-- 显示角色列表 -->
    <el-card>
        <el-button type="primary" @click="EditRole" v-hasButton="'add'">添加角色</el-button>
        <el-table border :data="roleList">
            <el-table-column label="序号" type="index" width="70px" align="center"></el-table-column>
            <el-table-column label="ID" prop="id" width="90px" align="center"></el-table-column>
            <el-table-column label="角色名称" prop="roleName" min-width="130px"></el-table-column>
            <el-table-column label="创建时间" prop="createTime" min-width="165px"></el-table-column>
            <el-table-column label="更新时间" prop="updateTime" min-width="165px"></el-table-column>
            <el-table-column label="操作" fixed="right" min-width="300px" align="center">
                <template #="{ row, $index }">
                    <el-button type="primary" icon="User" size="small" plain @click="setPermission(row)" v-hasButton="'assgin'">分配权限</el-button>
                    <el-button type="warning" icon="Edit" size="small" plain @click="EditRole(row)" v-hasButton="'update'">编辑</el-button>
                    <el-popconfirm :title="`确认删除 ${row.roleName} ?`" width="200px" @confirm="deleteRole(row.id)" v-hasButton="'remove'">
                        <template #reference>
                            <el-button type="danger" icon="Delete" size="small" plain>删除</el-button>
                        </template>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>
        <el-pagination v-model:current-page="pageNo" v-model:page-size="pageSize" :page-sizes="[5, 6, 7, 8]"
            :background="true" layout="prev, pager, next, jumper, ->, sizes, total" :total="total"
            @current-change="getRoleList(pageNo)" @size-change="getRoleList()" />
    </el-card>
    <!-- 对话框：添加角色 -->
    <el-dialog v-model="showEditRole" :title="role.id ? '修改角色' : '添加角色'">
        <el-form ref="roleform" :rules="rules" :model="role">
            <el-form-item label="角色名称" prop="roleName">
                <el-input v-model.trim="role.roleName" placeholder="请输入角色名称" clearable></el-input>
            </el-form-item>
        </el-form>
        <template #footer>
            <el-button type="primary" @click="confirmEditRole">确定</el-button>
            <el-button @click="showEditRole = false">取消</el-button>
        </template>
    </el-dialog>
    <!-- 抽屉狂：分配权限 -->
    <el-drawer v-model="showPermission" title="设置菜单与按钮权限">
        <template #default>
            <!-- 树形控件(显示多选框、默认全部展开) -->
            <el-tree ref="menuTree" :data="menuList" node-key="id" :props="defaultProps" show-checkbox accordion
                default-expand-all :default-checked-keys="defaultMenu" />
        </template>
        <template #footer>
            <div style="flex: auto">
                <el-button type="primary" @click="savePermission">确定</el-button>
                <el-button @click="showPermission = false">取消</el-button>
            </div>
        </template>
    </el-drawer>
</template>

<script setup lang="ts">
import type { AllRoles, UserRole } from '@/api/acl/user/type';
import type { ResRoleList, ResMenuList, MenuList } from '@/api/acl/role/type';
import { reqGetRoleList, reqAddOrUpdateRole, reqDeleteRole, reqUserPermission, reqSetPermission } from '@/api/acl/role';
import { nextTick, onMounted, ref } from 'vue';
import { ElMessage } from 'element-plus';
import Searchbox from './subComponent/searchbox.vue';

// 分页器数据
// 页码、每页数量、总页数
let pageNo = ref<number>(1)
let pageSize = ref<number>(6)
let total = ref<number>(0)
// 角色列表
let roleList = ref<AllRoles>([])

onMounted(() => {
    getRoleList();
})
// 获取角色列表
const getRoleList = async (pager = 1) => {
    pageNo.value = pager
    let result: ResRoleList
    // 根据是否搜索获取不同响应数据
    if (clickSearch.value && searchInput.value)
        result = await reqGetRoleList(pageNo.value, pageSize.value, searchInput.value);
    else result = await reqGetRoleList(pageNo.value, pageSize.value);
    if (result.code == 200) {
        roleList.value = result.data.records;
        total.value = result.data.total
    }
}

// 标记是否点击搜索
let clickSearch = ref<boolean>(false)
// 搜索框内容
let searchInput = ref<string>('')
// 点击搜索（获取子组件数据）
const searchRole = (value: string) => {
    clickSearch.value = true
    searchInput.value = value
    getRoleList()
}
// 点击重置（子组件事件）
const resetRoleList = () => {
    clickSearch.value = false
    searchInput.value = ''
    pageSize.value = 6
    getRoleList()
}

// 显示编辑角色对话框
let showEditRole = ref<boolean>(false)
// 编辑角色form表单实例
let roleform = ref()
// 当前角色
let role = ref<UserRole>({ roleName: '' })
/// 表单校验规则
const rules = {
    roleName: [{ required: true, min: 2, max: 15, message: '角色名称长度为2~15', trigger: 'change' }]
}
// 点击添加/编辑角色
const EditRole = (row?: UserRole) => {
    showEditRole.value = true
    // 需要等DOM加载后再处理数据
    nextTick(() => {
        roleform.value.resetFields();
        // 存在角色数据，则为修改，否则为添加
        if (row) role.value = { ...row }
        else role.value = { roleName: '' }
    })
}
// 点击对话框“确定”按钮（发请求）
const confirmEditRole = async () => {
    let result = await reqAddOrUpdateRole(role.value);
    if (result.code == 200) {
        ElMessage.success(role.value.id ? '修改成功' : '添加成功')
        // 关闭对话框
        showEditRole.value = false
        // 修改角色，则重新获取当前页
        if (role.value.id) getRoleList(pageNo.value)
        // 重新获取第一页
        else getRoleList()
    }
    else ElMessage.error(role.value.id ? '修改失败' : '添加失败')
}
// 删除角色
const deleteRole = async (roleid: number) => {
    let result = await reqDeleteRole(roleid);
    if (result.code == 200) {
        ElMessage.success('删除成功')
        // 删除后当页无数据
        if (roleList.value.length - 1) getRoleList(pageNo.value)
        else getRoleList(pageNo.value - 1)
    }
    else ElMessage.success('删除失败')
}

// 分配权限功能
let showPermission = ref<boolean>(false)
// 菜单列表（树形结构）
let menuList = ref<MenuList>([])
// 默认选中的菜单权限
let defaultMenu = ref<number[]>([])
// 树形组件实例
let menuTree = ref()
// 显示菜单抽屉框，获取菜单列表
const setPermission = async (row: UserRole) => {
    // 获取前清空菜单数据
    defaultMenu.value = []
    menuList.value = []
    role.value = row
    let result: ResMenuList = await reqUserPermission(row.id as number);
    if (result.code == 200) {
        // 获取菜单列表数据
        menuList.value = result.data;
        showPermission.value = true
        // 清空默认勾选的数据
        initPermission(menuList.value);

    }

}
// 设置树形的数据结构
const defaultProps = {
    children: 'children',  //表示子节点的属性名
    label: 'name',         //每行显示的属性名
}

/* 原数据中，若该节点的子节点中有被勾选 / 自身为叶子节点且被勾选，则select为true
    Tree组件中，若父节点勾选，则子节点全被勾选，与数据表示的意思不符合。
    但若子节点被勾选，则父节点自动变为半选或全选状态。
    所以可以直接对叶子节点进行判断和勾选，无需考虑父级
*/
// 设置初始勾选状态（递归）
const initPermission = (menu: MenuList) => {
    // 遍历子节点
    menu.forEach(item => {
        // 非叶子节点，则深度遍历
        if (item.children && item.children.length)
            initPermission(item.children)
        // 为叶子节点且被选中，则将id添加到默认的选择列表中
        else if (item.select) defaultMenu.value.push(item.id)
    })
}

// 确认设置权限
const savePermission = async () => {
    // 设置请求参数
    let id: number = role.value.id as number;
    let permission: number[] = [
        ...menuTree.value.getCheckedKeys(),
        ...menuTree.value.getHalfCheckedKeys()];
    let data = {
        permissionIdList: permission,
        roleId: id
    }

    let result = await reqSetPermission(data);
    if (result.code == 200) {
        ElMessage.success('设置成功')
        showPermission.value = false
        // 重新获取当前页面（即使更新当前用户的菜单和权限）
        window.location.reload();
    }
    else ElMessage.error('设置失败')
}
</script>

<style scoped lang="scss">
.el-card {
    margin-bottom: 10px;

    .el-table {
        margin: 15px 0;
    }
}

.top-form {
    display: flex;
    justify-content: space-between;
}
</style>